<template>
  <div v-if="generated === false" class="chat-ui">
    <div class="chat-header">
      <div>
        <a-button
          type="text"
          style="color: #1055ff; margin-left: 12px"
          @click="newChat"
          :disabled="loading"
        >
          <template #icon>
            <PlusOutlined />
          </template>
          新对话
        </a-button>
      </div>

      <a-popover>
        <template #content>
          <div
            v-for="option in models"
            :key="option.value"
            class="model-option"
            @click="selectModel(option.value)"
          >
            <img :src="option.icon" :alt="`${option.label} Icon`" />
            <span>{{ option.label }}</span>
          </div>
        </template>
        <div class="selected-model">
          <span class="model-name">{{ getSelectedModel.label }}</span>
          <img :src="getSelectedModel.icon" alt="模型图标" />
        </div>
      </a-popover>
    </div>
    <div v-if="messages.length === 0" class="welcome">
      <welcome @click="toolChange" />
    </div>
    <!-- 聊天窗口 -->
    <div v-else ref="scrollContainer" class="message-card" @wheel="handleWheel">
      <message-item
        v-if="messages.length > 0"
        v-for="(message, index) in messages"
        :message="message"
        :index="index"
        :isLast="messages.length > 1 && messages.length === index + 1"
        :loading="loading"
      />
    </div>
    <!-- 工具栏 -->
    <div style="width: 100%" v-if="toolType === null">
      <tool-bar :toolChange="toolChange" />
    </div>
    <!-- 消息发送区域 -->
    <div class="send-btn">
      <div
        v-if="toolType !== null"
        style="
          width: 100%;
          display: flex;
          align-items: center;
          justify-content: space-between;
          padding: 12px 24px;
          background-color: #f7f8fc;
        "
      >
        <div style="display: flex; align-items: center">
          <a class="tool-name">{{ toolTypeDesc[toolType].name }}</a>

          <!-- 附带参数 -->
          <!-- 翻译 -->
          <div v-if="toolType === 'translation'" class="tool-params">
            <a-select v-model:value="toolParams['translationSource']" style="width: 150px">
              <a-select-option value="auto">自动检测</a-select-option>
              <a-select-option v-for="item in languages" :value="item.key">
                {{ item.value }}
              </a-select-option>
            </a-select>
            <span style="margin: 0 20px"> -> </span>
            <a-select v-model:value="toolParams['translationTarget']" style="width: 150px">
              <a-select-option v-for="item in languages" :value="item.key">
                {{ item.value }}
              </a-select-option>
            </a-select>
          </div>
          <!-- 转换 -->
          <div v-if="toolType === 'conversion'" class="tool-params">
            <a-select v-model:value="toolParams['conversionSource']" style="width: 140px">
              <a-select-option value="Properties">Properties</a-select-option>
              <a-select-option value="Yaml">Yaml</a-select-option>
              <a-select-option value="Xml">Xml</a-select-option>
              <a-select-option value="Sql">Sql</a-select-option>
              <a-select-option value="Json">Json</a-select-option>
              <a-select-option value="Java实体类">Java实体类</a-select-option>
            </a-select>
            <span style="margin: 0 20px"> -> </span>
            <a-select v-model:value="toolParams['conversionTarget']" style="width: 140px">
              <a-select-option value="Properties">Properties</a-select-option>
              <a-select-option value="Yaml">Yaml</a-select-option>
              <a-select-option value="Xml">Xml</a-select-option>
              <a-select-option value="Sql">Sql</a-select-option>
              <a-select-option value="Json">Json</a-select-option>
              <a-select-option value="Java实体类">Java实体类</a-select-option>
            </a-select>
          </div>

          <div v-if="toolType === 'code'" class="tool-params">
            <div style="color: #a5a5a5">编程语言：</div>
            <a-select v-model:value="toolParams['codeType']" style="width: 140px">
              <a-select-option value="Java">Java</a-select-option>
              <a-select-option value="Python">Python</a-select-option>
              <a-select-option value="Go">Go</a-select-option>
              <a-select-option value="Kotlin">Kotlin</a-select-option>
              <a-select-option value="Rust">Rust</a-select-option>
              <a-select-option value="Vue">Vue</a-select-option>
              <a-select-option value="React">React</a-select-option>
              <a-select-option value="JavaScript">JavaScript</a-select-option>
              <a-select-option value="C语言">C语言</a-select-option>
              <a-select-option value="C++">C++</a-select-option>
              <a-select-option value="C#">C#</a-select-option>
            </a-select>
          </div>
          <div v-if="toolType === 'crud'" class="tool-params">
            <a
              style="color: #1055ff; cursor: pointer; margin-left: 20px"
              href="/#/agent/code-generator"
            >
              高级用法
            </a>
          </div>
        </div>
        <a style="font-size: 20px; color: #a5a5a5; cursor: pointer" @click="cancelTool">x</a>
      </div>

      <div v-if="fileName && fileName.length > 0" class="file-card">
        <div style="display: flex; align-items: center; justify-content: space-between">
          <div class="file-name">{{ fileName }}</div>
          <img
            src="/icon/close2.svg"
            style="width: 12px; margin-left: 12px; cursor: pointer"
            @click="deleteFile"
          />
        </div>
        <div v-if="fileParser === 2" style="font-size: 10px; color: rgba(135, 138, 171, 0.6)">
          文件解析成功
        </div>
        <div v-else-if="fileParser === 3" style="font-size: 10px; color: #ff0000">文件解析失败</div>
        <div v-else style="font-size: 10px; color: rgba(135, 138, 171, 0.6)">
          <a-spin :indicator="indicator">文件解析中 ...</a-spin>
        </div>
      </div>

      <div
        style="
          padding: 6px 8px 8px 16px;
          background-color: #ffffff;
          display: flex;
          align-items: flex-end;
        "
      >
        <div style="width: 100%; display: flex; align-items: flex-end">
          <div style="display: flex; align-items: center">
            <a-upload
              :custom-request="customRequest"
              :show-upload-list="false"
              :max-count="1"
              :beforeUpload="handleFileChange"
            >
              <a-tooltip>
                <template #title>上传附件（仅识别文字）</template>
                <div style="display: flex; align-items: center">
                  <LinkOutlined class="upload-btn" />
                </div>
              </a-tooltip>
            </a-upload>
          </div>
          <a-textarea
            :disabled="loading"
            class="ant-input"
            v-model:value="input"
            :placeholder="toolType ? toolTypeDesc[toolType].placeholder : '遇事不决问AI'"
            :auto-size="{ minRows: 1, maxRows: 6 }"
            :bordered="false"
            @keydown.enter="pressEnter"
            autofocus
          />
        </div>
        <img
          v-if="loading === false"
          @click="send"
          src="/icon/send2.svg"
          :class="input.trim().length > 0 ? 'send-icon' : 'send-icon-disable'"
        />
        <div v-else class="stop-icon" @click="stop">
          <img src="/icon/stop.svg" style="width: 20px" />
        </div>
      </div>
    </div>

    <div class="to-bottom-card" v-if="showToBottom" @click="toBottom">
      <img src="/icon/to-bottom.svg" class="to-bottom" />
    </div>

    <div class="footer">
      <div class="ga-div">
        <!-- 公安备案图标链接 -->
        <a
          target="_blank"
          href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=42018502006848"
          style="height: 30px; display: inline-block"
        >
          <img src="/icon/ga.png" alt="公安备案图标" />
        </a>
        <!-- 公安备案号链接 -->
        <a
          target="_blank"
          href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=42018502006848"
          class="ga-a"
        >
          <span class="ga-p"> 鄂公网安备 42018502006848号 </span>
        </a>
        <!-- ICP备案号链接 -->
        <a href="https://beian.miit.gov.cn" target="_blank" class="ga-a">
          <span class="icp">鄂ICP备2023014101号-1</span>
        </a>
      </div>
    </div>
  </div>

  <div v-if="generated === true && files.length > 0" style="width: 100%">
    <code-tree :files="files" @close="closeTree" />
  </div>

  <div v-if="openCollection">
    <a-drawer v-model:open="openCollection" title="我的收藏" placement="right" width="600px">
      <collection-drawer />
    </a-drawer>
  </div>
</template>

<script setup>
import Http from '@/api/http'
import router from '@/router'
import { isLogin, useUserStore } from '@/stores/user'
import CodeTree from '@/views/component/code-tree.vue'
import CollectionDrawer from '@/views/component/collection-drawer.vue'
import messageItem from '@/views/component/messageItem.vue'
import ToolBar from '@/views/component/tool-bar.vue'
import { LinkOutlined, LoadingOutlined, PlusOutlined } from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import { computed, h, onMounted, onUnmounted, ref, watch } from 'vue'
import Welcome from './welcome.vue'
const files = ref([])
const generated = ref(false)
const generateLoading = ref(false)
const userInfoStore = useUserStore()
const indicator = h(LoadingOutlined, {
  style: {
    fontSize: '14px'
  },
  spin: true
})

const models = ref([
  {
    label: 'DeepSeek',
    value: 'deepseek-v3-250324',
    icon: '/icon/deepseek.svg'
  },
  {
    label: 'DeepSeek R1',
    value: 'deepseek-r1-250528',
    icon: '/icon/deepseek.svg'
  },
  {
    label: '豆包',
    value: 'doubao-seed-1-6-250615',
    icon: '/icon/doubao.png'
  },
  {
    label: 'Kimi-K2',
    value: 'kimi-k2-250711',
    icon: '/icon/kimi.png'
  },
  {
    label: '智谱 AI',
    value: 'glm-4.5',
    icon: '/icon/chatglm.png'
  },
  {
    label: '文心一言 3.5',
    value: 'ernie-3.5-128k',
    icon: '/icon/ernie-bot.png'
  },
  {
    label: '文心一言 4.5',
    value: 'ernie-4.5-turbo-128k',
    icon: '/icon/ernie-bot.png'
  },
  {
    label: '通义千问',
    value: 'qwen-plus',
    icon: '/icon/tongyi.png'
  },
  {
    label: '通义千问 Max',
    value: 'qwen-max',
    icon: '/icon/tongyi.png'
  }
])
const model = ref('deepseek-v3-250324')
const openCollection = ref(false)
const scrollContainer = ref(null)
const autoRefreshScroll = ref(true)
const showToBottom = ref(false)
const input = ref('')
const messages = ref([])
const loading = ref(false)
const clientId = ref(null)
const sessionId = ref(null)
const toolType = ref(null)
const toolTypeDesc = ref({
  code: {
    name: '代码模式',
    placeholder: '输入问题'
  },
  crud: {
    name: 'Java代码生成器',
    placeholder: '输入SQL / 需求'
  },
  translation: {
    name: 'AI翻译',
    placeholder: '输入要翻译的文本'
  },
  conversion: {
    name: '格式转换器',
    placeholder: '输入要转换的内容'
  }
})
const stopFlag = ref(false)
const languages = [
  { key: 'English', value: '英语' },
  { key: 'Chinese', value: '简体中文' },
  { key: 'Traditional Chinese', value: '繁体中文' },
  { key: 'Russian', value: '俄语' },
  { key: 'Japanese', value: '日语' },
  { key: 'Korean', value: '韩语' },
  { key: 'Spanish', value: '西班牙语' },
  { key: 'French', value: '法语' },
  { key: 'Portuguese', value: '葡萄牙语' },
  { key: 'German', value: '德语' },
  { key: 'Italian', value: '意大利语' },
  { key: 'Thai', value: '泰语' },
  { key: 'Vietnamese', value: '越南语' },
  { key: 'Indonesian', value: '印度尼西亚语' },
  { key: 'Malay', value: '马来语' },
  { key: 'Arabic', value: '阿拉伯语' },
  { key: 'Hindi', value: '印地语' },
  { key: 'Hebrew', value: '希伯来语' },
  { key: 'Burmese', value: '缅甸语' },
  { key: 'Tamil', value: '泰米尔语' },
  { key: 'Urdu', value: '乌尔都语' },
  { key: 'Bengali', value: '孟加拉语' },
  { key: 'Polish', value: '波兰语' },
  { key: 'Dutch', value: '荷兰语' },
  { key: 'Romanian', value: '罗马尼亚语' },
  { key: 'Turkish', value: '土耳其语' },
  { key: 'Khmer', value: '高棉语' },
  { key: 'Lao', value: '老挝语' },
  { key: 'Cantonese', value: '粤语' },
  { key: 'Czech', value: '捷克语' },
  { key: 'Greek', value: '希腊语' },
  { key: 'Swedish', value: '瑞典语' },
  { key: 'Hungarian', value: '匈牙利语' },
  { key: 'Danish', value: '丹麦语' },
  { key: 'Finnish', value: '芬兰语' },
  { key: 'Ukrainian', value: '乌克兰语' },
  { key: 'Bulgarian', value: '保加利亚语' },
  { key: 'Serbian', value: '塞尔维亚语' },
  { key: 'Telugu', value: '泰卢固语' },
  { key: 'Afrikaans', value: '南非荷兰语' },
  { key: 'Armenian', value: '亚美尼亚语' },
  { key: 'Assamese', value: '阿萨姆语' },
  { key: 'Asturian', value: '阿斯图里亚斯语' },
  { key: 'Basque', value: '巴斯克语' },
  { key: 'Belarusian', value: '白俄罗斯语' },
  { key: 'Bosnian', value: '波斯尼亚语' },
  { key: 'Catalan', value: '加泰罗尼亚语' },
  { key: 'Cebuano', value: '宿务语' },
  { key: 'Croatian', value: '克罗地亚语' },
  { key: 'Egyptian Arabic', value: '埃及阿拉伯语' },
  { key: 'Estonian', value: '爱沙尼亚语' },
  { key: 'Galician', value: '加利西亚语' },
  { key: 'Georgian', value: '格鲁吉亚语' },
  { key: 'Gujarati', value: '古吉拉特语' },
  { key: 'Icelandic', value: '冰岛语' },
  { key: 'Javanese', value: '爪哇语' },
  { key: 'Kannada', value: '卡纳达语' },
  { key: 'Kazakh', value: '哈萨克语' },
  { key: 'Latvian', value: '拉脱维亚语' },
  { key: 'Lithuanian', value: '立陶宛语' },
  { key: 'Luxembourgish', value: '卢森堡语' },
  { key: 'Macedonian', value: '马其顿语' },
  { key: 'Maithili', value: '马加希语' },
  { key: 'Maltese', value: '马耳他语' },
  { key: 'Marathi', value: '马拉地语' },
  { key: 'Mesopotamian Arabic', value: '美索不达米亚阿拉伯语' },
  { key: 'Moroccan Arabic', value: '摩洛哥阿拉伯语' },
  { key: 'Najdi Arabic', value: '内志阿拉伯语' },
  { key: 'Nepali', value: '尼泊尔语' },
  { key: 'North Azerbaijani', value: '北阿塞拜疆语' },
  { key: 'North Levantine Arabic', value: '北黎凡特阿拉伯语' },
  { key: 'Northern Uzbek', value: '北乌兹别克语' },
  { key: 'Norwegian Bokmål', value: '书面语挪威语' },
  { key: 'Norwegian Nynorsk', value: '新挪威语' },
  { key: 'Occitan', value: '奥克语' },
  { key: 'Odia', value: '奥里亚语' },
  { key: 'Pangasinan', value: '邦阿西楠语' },
  { key: 'Sicilian', value: '西西里语' },
  { key: 'Sindhi', value: '信德语' },
  { key: 'Sinhala', value: '僧伽罗语' },
  { key: 'Slovak', value: '斯洛伐克语' },
  { key: 'Slovenian', value: '斯洛文尼亚语' },
  { key: 'South Levantine Arabic', value: '南黎凡特阿拉伯语' },
  { key: 'Swahili', value: '斯瓦希里语' },
  { key: 'Tagalog', value: '他加禄语' },
  { key: 'Ta’izzi-Adeni Arabic', value: '塔伊兹-亚丁阿拉伯语' },
  { key: 'Tosk Albanian', value: '托斯克阿尔巴尼亚语' },
  { key: 'Tunisian Arabic', value: '突尼斯阿拉伯语' },
  { key: 'Venetian', value: '威尼斯语' },
  { key: 'Waray', value: '瓦莱语' },
  { key: 'Welsh', value: '威尔士语' },
  { key: 'Western Persian', value: '西波斯语' }
]
const toolParams = ref({
  translationSource: 'auto',
  translationTarget: 'Chinese',
  conversionSource: 'Properties',
  conversionTarget: 'Yaml',
  codeType: 'Java'
})

// 生成器配置
const generatorConfig = ref({
  //接口前缀
  apiPathPrefix: '/api',
  //去除表前缀
  tableNamePrefix: 't_',
  //包名
  basePackage: 'com.tool4j.ai',
  //作者
  author: '',
  //orm框架
  ormType: 'mybatisPlus',
  //是否使用lombok
  useLombok: true,
  //是否使用swagger
  swaggerSupport: false,
  //是否开启类注释
  useClassComment: true,
  //是否开启方法注释
  useMethodComment: true,
  //是否开启字段注释
  useFieldComment: true,
  //代码模板
  templateId: null,
  methodConfigMap: {
    findPage: {
      label: '分页查询',
      name: 'findPage',
      apiPath: '/findPage',
      enabled: true
    },
    findList: {
      label: '列表查询',
      name: 'findList',
      apiPath: '/findList',
      enabled: true
    },
    findById: {
      label: '查询详情',
      name: 'findById',
      apiPath: '/{id}',
      enabled: true
    },
    save: {
      label: '新增',
      name: 'insert',
      apiPath: '',
      enabled: true
    },
    update: {
      label: '修改',
      name: 'update',
      apiPath: '',
      enabled: true
    },
    delete: {
      label: '删除',
      name: 'delete',
      apiPath: '/{id}',
      enabled: true
    }
  }
})
const file = ref(null)
const fileName = ref('')
const fileContent = ref('')
const fileParser = ref(1)

function newChat() {
  sessionId.value = generateId()
  messages.value = []
  input.value = ''
  toolType.value = null
  toolParams.value = {}
  stopFlag.value === true
  loading.value = false
}

function closeTree() {
  generated.value = false
  files.value = []
}

function deleteFile() {
  file.value = null
  fileName.value = ''
  fileContent.value = ''
}

function customRequest() {
  const formData = new FormData()
  formData.append('file', file.value)
  fileParser.value = 1
  Http.post('/api/file/readFile', formData)
    .then((res) => {
      fileContent.value = res
      fileParser.value = 2
    })
    .catch((err) => {
      message.error(err)
      fileParser.value = 3
    })
}

function handleFileChange(fileData) {
  file.value = fileData
  fileName.value = fileData.name
}

const getSelectedModel = computed(() => {
  return models.value.find((m) => m.value === model.value) || {}
})

function selectModel(value) {
  model.value = value
}

function cancelTool() {
  toolType.value = null
}

function toolChange(type) {
  if (type === 'chat') {
    toolType.value = null
  } else if (type === 'collection') {
    openCollection.value = true
  } else {
    toolType.value = type
  }
}

function pressEnter(e) {
  if (e && e.keyCode === 13) {
    if (e.shiftKey) {
      return
    }
  }
  e.preventDefault()
  send()
}

/**
 * 生成随机ID
 */
function generateId() {
  const timestamp = Date.now() // 毫秒级时间戳
  const randomNum = Math.floor(Math.random() * 10000) // 0-9999 的随机数
  return `${timestamp}${randomNum}`
}

function send() {
  if (loading.value === true) {
    message.warning('请等待AI回答完后再发送')
    return
  }
  if (input.value.trim().length === 0) {
    return
  }
  messages.value.push({
    id: generateId(),
    role: 'user',
    content: input.value
  })
  const requestParams = {
    modelName: model.value,
    chatId: generateId(),
    clientId: clientId.value,
    sessionId: sessionId.value,
    content: input.value,
    toolType: toolType.value,
    toolParams: toolParams.value
  }
  if (toolType.value === 'crud') {
    requestParams['toolParams']['javaCodeConfig'] = generatorConfig.value
    generateLoading.value = true
  }
  if (fileContent.value) {
    requestParams['fileContent'] = fileContent.value
  }
  input.value = ''
  stopFlag.value = false
  // 滚动到最底部
  toBottom()
  Http.post('/api/chat/stream', requestParams)
    .then((res) => {
      loading.value = true
    })
    .catch((err) => {
      loading.value = false
      stopFlag.value = false
      message.error('系统异常，请联系站长')
    })
}

// 监听滚动事件
function handleWheel(event) {
  if (scrollContainer.value === null) {
    return
  }
  if (event.deltaY > 0) {
    if (
      scrollContainer.value.scrollTop + scrollContainer.value.clientHeight + 100 >=
      scrollContainer.value.scrollHeight
    ) {
      autoRefreshScroll.value = true
      showToBottom.value = false
    }
  } else if (event.deltaY < 0) {
    autoRefreshScroll.value = false
    showToBottom.value = true
  }
}

function refreshScroll() {
  if (scrollContainer.value === null) {
    return
  }
  if (autoRefreshScroll.value === true) {
    scrollContainer.value.scrollTop = scrollContainer.value.scrollHeight
  }
}

function toBottom() {
  if (scrollContainer.value === null) {
    return
  }
  scrollContainer.value.scrollTop = scrollContainer.value.scrollHeight
  autoRefreshScroll.value = true
  showToBottom.value = false
}

// SSE 实例
let eventSource = null

function stop() {
  stopFlag.value = true
  loading.value = false
}

function getMessages(sessionId) {
  Http.get('/api/chat/getMessages/' + sessionId).then((res) => {
    messages.value = res.data
  })
}

onMounted(() => {
  if (!isLogin()) {
    return
  }
  if (userInfoStore && userInfoStore.config) {
    generatorConfig.value = userInfoStore.config
  }

  // 监听路由 query 中 id 的变化
  watch(
    () => router.currentRoute.value.query.id,
    (newId) => {
      if (newId) {
        sessionId.value = newId
        getMessages(newId)
      } else {
        sessionId.value = generateId()
        messages.value = [] // 可选：清空消息
      }
    },
    { immediate: true } // 立即执行一次，相当于初始化
  )

  clientId.value = generateId()
  // 使用 URL 参数传递认证信息（如 token）
  const sseUrl = Http.baseUrl + '/sse/event/connect?clientId=' + clientId.value
  eventSource = new EventSource(sseUrl)
  // 监听 message 事件（默认事件）
  eventSource.onmessage = (event) => {
    if (event.data === 'event: stop' || stopFlag.value === true) {
      loading.value = false
      return
    }
    try {
      const data = JSON.parse(event.data)
      if (data.file) {
        files.value = JSON.parse(data.file)
        generated.value = true
        loading.value = false
        generateLoading.value = false
      }
      if (data.content) {
        const filterMessages = messages.value.find((item) => item.id === data.chatId)
        if (filterMessages) {
          if (toolType.value === 'translation') {
            filterMessages.content = data.content
          } else {
            filterMessages.content += data.content
          }
        } else {
          messages.value.push({
            id: data.chatId,
            role: 'assistant',
            content: data.content
          })
        }

        refreshScroll()
      }
    } catch (err) {
      console.error(err)
    }
  }
  // 监听自定义事件
  eventSource.addEventListener('complete', (event) => {
    loading.value = false
  })
  // 错误处理
  eventSource.onerror = (err) => {
    console.error('SSE error:', err)
    loading.value = false
  }
})

onUnmounted(() => {
  if (eventSource) {
    eventSource.close()
  }
})
</script>

<style scoped>
.chat-ui {
  display: grid;
  grid-template-rows: auto 1fr auto;
  height: 100vh;
  background-color: #ffffff;
}

.send-btn {
  overflow: hidden;
  border: 1px solid #615ced;
  border-radius: 20px;
  margin: 0 12px 4px 12px;
}

.send-icon {
  width: 34px;
  height: 34px;
  padding: 4px;
  border-radius: 50%;
  background-color: #615ced;
}

.send-icon-disable {
  width: 34px;
  height: 34px;
  padding: 4px;
  border-radius: 50%;
  background-color: #d6d5de;
}

.send-icon:hover {
  cursor: pointer;
  background-color: #807bf4;
}

.send-icon-disable:hover {
  cursor: pointer;
  background-color: #dbdbdf;
}

.ant-input {
  overflow-y: hidden;
}

.ant-input:hover {
  overflow-y: auto;
}

.message-card {
  max-height: calc(100vh - 80px);
  overflow: auto;
  margin: 0 0 12px 10px;
}

.tool-name {
  background: #eeedff;
  color: #615ced;
  padding: 4px 12px;
  border-radius: 16px;
  cursor: pointer;
}

.tool-desc {
  margin-left: 20px;
  color: #a5a5a5;
  font-size: 12px;
}

.stop-icon {
  padding: 4px;
  border-radius: 50%;
  border: 1px solid #d81e06;
  cursor: pointer;
}

.tool-params {
  display: flex;
  align-items: center;
  margin-left: 20px;
}

.to-bottom-card {
  width: 40px;
  padding: 10px;
  border-radius: 50%;
  background: #ffffff;
  position: absolute;
  right: 40%;
  bottom: 120px;
  cursor: pointer;
  transition: 0.3s ease;
}

.to-bottom-card:hover {
  background: #e6e3f6;
}

.to-bottom {
  width: 20px;
}

.chat-header {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 50px;
}

.selected-model {
  width: 160px;
  cursor: pointer;
  padding: 8px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  margin-left: 20px;
}

.selected-model :hover {
  color: #7e5ced;
}

.model-name {
  font-size: 16px;
  font-weight: 600;
}

.selected-model img {
  margin-left: 8px;
  width: 20px;
  height: 20px;
}

.model-option {
  padding: 6px 12px;
  cursor: pointer;
  display: flex;
  align-items: center;
}

.model-option:hover {
  border-radius: 6px;
  background-color: #e0dafe;
}

.model-option img {
  margin-right: 8px;
  width: 20px;
  height: 20px;
}

.upload-btn {
  width: 34px;
  height: 34px;
  font-size: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  border: 1px solid #f5f5f5;
  cursor: pointer;
  background-color: #f5f5f5;
  padding: 4px;
}

.upload-btn :hover {
  color: #1677ff;
}

.file-card {
  max-width: 400px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 6px 24px;
  border: 1px solid #dcdcdc;
  border-radius: 6px;
  margin: 6px 20px;
}

.file-name {
  max-width: 400px;
  color: #000000;
  white-space: nowrap; /* 不换行 */
  overflow: hidden; /* 超出部分隐藏 */
  text-overflow: ellipsis; /* 超出部分显示省略号 */
}

.welcome {
  width: 100%;
  max-height: calc(100vh - 80px);
  overflow: auto;
}

.config-modal :deep(.ant-modal-body) {
  max-height: 60vh;
  overflow-y: auto;
}

.module-title {
  font-weight: 600;
  padding: 12px;
  border-bottom: 1px solid #f5f5f5;
  margin-bottom: 12px;
}

.row {
  height: 40px;
}

.mb-4 {
  margin-bottom: 6px;
}
.mt-4 {
  margin-top: 6px;
}
.mr-2 {
  margin-right: 8px;
}
.flex {
  display: flex;
}
.justify-end {
  justify-content: flex-end;
}

.footer {
  width: 100%;
  text-align: center;
  background: #ffffff;
}

.ga-div {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 0 auto;
}

.ga-a {
  display: inline-block;
  text-decoration: none;
  line-height: 24px;
}

.ga-p {
  line-height: 24px;
  margin: 0 30px 0 5px;
  color: #8b8da4;
}

.icp {
  line-height: 24px;
  color: #8b8da4;
}
</style>
